From bfdcfc10bbd80cf3b04ee2ef1c1428f7b44d7a38 Mon Sep 17 00:00:00 2001 From: "kaf24@firebug.cl.cam.ac.uk" Date: Fri, 11 Nov 2005 10:41:25 +0100 Subject: [PATCH] Add MOVSX instr support to VMX MMIO decoder. Signed-off-by: Xin Li --- xen/arch/x86/vmx_io.c | 50 +++++++++++++++++++++++++++--- xen/arch/x86/vmx_platform.c | 43 ++++++++++++++++--------- xen/arch/x86/vmx_vlapic.c | 4 ++- xen/include/asm-x86/vmx_platform.h | 23 +++++++------- 4 files changed, 90 insertions(+), 30 deletions(-) diff --git a/xen/arch/x86/vmx_io.c b/xen/arch/x86/vmx_io.c index 5b879bd52e..7cbdafb277 100644 --- a/xen/arch/x86/vmx_io.c +++ b/xen/arch/x86/vmx_io.c @@ -459,14 +459,56 @@ static void vmx_mmio_assist(struct cpu_user_regs *regs, ioreq_t *p, } break; - case INSTR_MOVZ: + case INSTR_MOVZX: if (dst & REGISTER) { + switch (size) { + case BYTE: + p->u.data &= 0xFFULL; + break; + + case WORD: + p->u.data &= 0xFFFFULL; + break; + + case LONG: + p->u.data &= 0xFFFFFFFFULL; + break; + + default: + printk("Impossible source operand size of movzx instr: %d\n", size); + domain_crash_synchronous(); + } index = operand_index(dst); + set_reg_value(operand_size(dst), index, 0, regs, p->u.data); + } + break; + + case INSTR_MOVSX: + if (dst & REGISTER) { switch (size) { - case BYTE: p->u.data = p->u.data & 0xFFULL; break; - case WORD: p->u.data = p->u.data & 0xFFFFULL; break; - case LONG: p->u.data = p->u.data & 0xFFFFFFFFULL; break; + case BYTE: + p->u.data &= 0xFFULL; + if ( p->u.data & 0x80ULL ) + p->u.data |= 0xFFFFFFFFFFFFFF00ULL; + break; + + case WORD: + p->u.data &= 0xFFFFULL; + if ( p->u.data & 0x8000ULL ) + p->u.data |= 0xFFFFFFFFFFFF0000ULL; + break; + + case LONG: + p->u.data &= 0xFFFFFFFFULL; + if ( p->u.data & 0x80000000ULL ) + p->u.data |= 0xFFFFFFFF00000000ULL; + break; + + default: + printk("Impossible source operand size of movsx instr: %d\n", size); + domain_crash_synchronous(); } + index = operand_index(dst); set_reg_value(operand_size(dst), index, 0, regs, p->u.data); } break; diff --git a/xen/arch/x86/vmx_platform.c b/xen/arch/x86/vmx_platform.c index 386ac55e40..2ee14c65ec 100644 --- a/xen/arch/x86/vmx_platform.c +++ b/xen/arch/x86/vmx_platform.c @@ -581,25 +581,39 @@ static int vmx_decode(int vm86, unsigned char *opcode, struct instruction *instr } switch (*++opcode) { - case 0xB6: /* movz m8, r16/r32 */ - instr->instr = INSTR_MOVZ; + case 0xB6: /* movzx m8, r16/r32/r64 */ + instr->instr = INSTR_MOVZX; GET_OP_SIZE_FOR_NONEBYTE(instr->op_size); index = get_index(opcode + 1, rex); instr->operand[0] = mk_operand(BYTE, 0, 0, MEMORY); instr->operand[1] = mk_operand(instr->op_size, index, 0, REGISTER); return DECODE_success; - case 0xB7: /* movz m16/m32, r32/r64 */ - instr->instr = INSTR_MOVZ; + case 0xB7: /* movzx m16/m32, r32/r64 */ + instr->instr = INSTR_MOVZX; + GET_OP_SIZE_FOR_NONEBYTE(instr->op_size); index = get_index(opcode + 1, rex); - if (rex & 0x8) { - instr->op_size = LONG; - instr->operand[1] = mk_operand(QUAD, index, 0, REGISTER); - } else { - instr->op_size = WORD; - instr->operand[1] = mk_operand(LONG, index, 0, REGISTER); - } - instr->operand[0] = mk_operand(instr->op_size, 0, 0, MEMORY); + if (rex & 0x8) + instr->operand[0] = mk_operand(LONG, 0, 0, MEMORY); + else + instr->operand[0] = mk_operand(WORD, 0, 0, MEMORY); + instr->operand[1] = mk_operand(instr->op_size, index, 0, REGISTER); + return DECODE_success; + + case 0xBE: /* movsx m8, r16/r32/r64 */ + instr->instr = INSTR_MOVSX; + GET_OP_SIZE_FOR_NONEBYTE(instr->op_size); + index = get_index(opcode + 1, rex); + instr->operand[0] = mk_operand(BYTE, 0, 0, MEMORY); + instr->operand[1] = mk_operand(instr->op_size, index, 0, REGISTER); + return DECODE_success; + + case 0xBF: /* movsx m16, r32/r64 */ + instr->instr = INSTR_MOVSX; + GET_OP_SIZE_FOR_NONEBYTE(instr->op_size); + index = get_index(opcode + 1, rex); + instr->operand[0] = mk_operand(WORD, 0, 0, MEMORY); + instr->operand[1] = mk_operand(instr->op_size, index, 0, REGISTER); return DECODE_success; case 0xA3: /* bt r32, m32 */ @@ -702,7 +716,7 @@ static void mmio_operands(int type, unsigned long gpa, struct instruction *inst, send_mmio_req(type, gpa, 1, inst->op_size, value, IOREQ_WRITE, 0); } else if (inst->operand[0] & MEMORY) { /* dest is register */ /* send the request and wait for the value */ - if (inst->instr == INSTR_MOVZ) + if ( (inst->instr == INSTR_MOVZX) || (inst->instr == INSTR_MOVSX) ) send_mmio_req(type, gpa, 1, size_reg, 0, IOREQ_READ, 0); else send_mmio_req(type, gpa, 1, inst->op_size, 0, IOREQ_READ, 0); @@ -827,7 +841,8 @@ void handle_mmio(unsigned long va, unsigned long gpa) break; } - case INSTR_MOVZ: + case INSTR_MOVZX: + case INSTR_MOVSX: mmio_operands(IOREQ_TYPE_COPY, gpa, &mmio_inst, mmio_opp, regs); break; diff --git a/xen/arch/x86/vmx_vlapic.c b/xen/arch/x86/vmx_vlapic.c index eb637bf80b..96c8f9c56c 100644 --- a/xen/arch/x86/vmx_vlapic.c +++ b/xen/arch/x86/vmx_vlapic.c @@ -567,7 +567,9 @@ static unsigned long vlapic_read(struct vcpu *v, unsigned long address, if ( len != 4) { /* some bugs on kernel cause read this with byte*/ - printk("Local APIC read with len = %lx, should be 4 instead\n", len); + VMX_DBG_LOG(DBG_LEVEL_VLAPIC, + "Local APIC read with len = %lx, should be 4 instead\n", + len); } alignment = offset & 0x3; diff --git a/xen/include/asm-x86/vmx_platform.h b/xen/include/asm-x86/vmx_platform.h index ad71bc5b9f..3e7563fe5c 100644 --- a/xen/include/asm-x86/vmx_platform.h +++ b/xen/include/asm-x86/vmx_platform.h @@ -55,17 +55,18 @@ #define REPNZ 0x2 #define OVERLAP 0x4 -#define INSTR_PIO 1 -#define INSTR_OR 2 -#define INSTR_AND 3 -#define INSTR_XOR 4 -#define INSTR_CMP 5 -#define INSTR_MOV 6 -#define INSTR_MOVS 7 -#define INSTR_MOVZ 8 -#define INSTR_STOS 9 -#define INSTR_TEST 10 -#define INSTR_BT 11 +#define INSTR_PIO 1 +#define INSTR_OR 2 +#define INSTR_AND 3 +#define INSTR_XOR 4 +#define INSTR_CMP 5 +#define INSTR_MOV 6 +#define INSTR_MOVS 7 +#define INSTR_MOVZX 8 +#define INSTR_MOVSX 9 +#define INSTR_STOS 10 +#define INSTR_TEST 11 +#define INSTR_BT 12 struct instruction { __s8 instr; /* instruction type */ -- 2.30.2